/**
 * 这个文件是用来构建项目的
 * 1. 读取项目配置文件 data/xx/data.json
 * 2. 通过json和template生成对应的文件
 * 3. 通过配生成签名
 * 4. 打包
 */
// 队列执行 移动文件到对应目录 (异步执行=签名->添加模块->添加权限)3个都执行结束 ->打包 copy到项目的project对应的目录下面
// 异步执行下面4个
// 1.移动文件到对应目录
// 2.签名
// 3.添加模块
// 4.添加权限
// 等待4个都执行结束 Promise.all
// 执行打包
// 打包结束后在base/baseAndroidSDK/[0]/HBuilder-Integrate-AS/simpleDemo/release/simpleDemo-release.apk 移动到项目的project对应的目录下面
const fs = require("fs"); // 系统模块 无需安装
const compressing = require("compressing"); // 需要安装 npm install compressing
const path = require("path"); // 系统模块 无需安装
const { addLog ,copyDir} = require("../utils");
const { iosChangeFile, iosSign, outIos } = require("./iosBuild");
const { copySdk } = require("./sdk");
let proPath = "";
const {
  androidChangeFile,
  androidSign,
  outAndroid,
} = require("./androidBuild");
const { getData, setData } = require("./data");
const { basePath } = require("../config");

const JSON5 = require("json5");
let baseLibDir,outLibDir,outJavaDir,userLibDir
function getDir() {
  let sdkDir =  fs.readdirSync(path.resolve(basePath,'baseAndroidSDK')).filter(item=>item != '.DS_Store')
  sdkDir = sdkDir.filter(item=>{
    return item.indexOf('Android') != -1
  })[0]
  // 还原libs文件夹
  baseLibDir =path.resolve(basePath,'baseAndroidSDK',sdkDir,'UniPlugin-Hello-AS/app/libs')
  outLibDir = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/libs')    
  outJavaDir = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/src/main/java')
  unipluginsDir = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/src/main/assets')
  dcloud_uniplugins = path.resolve(basePath,'baseAndroidSDK',sdkDir,'UniPlugin-Hello-AS/app/src/main/assets/dcloud_uniplugins.json')
  addLog("初始化libs:" + sdkDir);
}


let queue = []; // 队列
let isRun = false; // 是否在运行
let endItem = []; // 准备结束
// 执行队列
function runQueue() {
  if (isRun) return;
  if (queue.length) {
    isRun = true;
    let task = queue.shift();
    let projectData = getData(task.projectName);
    let isPlugins = fs.existsSync(  path.resolve(proPath,'dcloud_uniplugins.json'))
    if(isPlugins){
      userLibDir = path.resolve(proPath,'nativeplugins')
    }
    buildIng(task, projectData)
      .then( () => {
        isRun = false;
        addLog("构建成功:返回下载地址", task.projectName);
        
        // 打包成功移动到public/uploadfile/{projectName}/out.apk
        let sdkDir =  fs.readdirSync(path.resolve(basePath,'baseAndroidSDK')).filter(item=>item != '.DS_Store')
        sdkDir = sdkDir.filter(item=>{
          return item.indexOf('Android') != -1
        })[0]
        let prePath = path.resolve(basePath,'baseAndroidSDK',sdkDir,'HBuilder-Integrate-AS/simpleDemo/build/outputs/apk/release/simpleDemo-release.apk')
        let outPath = path.resolve(__dirname, "../../public/uploadfile/", task.projectName, task.projectName+".apk")
         copySdk(prePath, outPath).then(() => {
          projectData["outApk"] = "/uploadfile/"+task.projectName+"/"+task.projectName+".apk"
          setData(task.projectName, projectData);
         }).finally(() => {
          runQueue();
         })

      })
      .catch(() => {
        isRun = false;
        runQueue();
      })
      .finally(() => {

        global.building = global.building.filter((item) => {
          return !(
            item.type == "Android" && item.projectName == task.projectName
          );
        });
        projectData.build[task.type] = false;
        setData(task.projectName, projectData);
      });
  }
}

// 执行构建
 function buildIng(data, projectData) {
  console.log(" global.building", global.building);
  return new Promise(async (resolve, reject) => {
    addLog("开始构建项目:" + data.projectName, data.projectName);
    console.log("开始构建项目", data.projectName);
    addLog("初始化libs:" + data.projectName, data.projectName);
    let isPlugins = fs.existsSync(  path.resolve(proPath,'dcloud_uniplugins.json'))

    fs.rmSync(outLibDir, { recursive: true, force: true });
    fs.rmSync(outJavaDir, { recursive: true, force: true });
    fs.rmSync(dcloud_uniplugins, { recursive: true, force: true })

    fs.mkdirSync(outLibDir, { recursive: true });
    fs.mkdirSync(outJavaDir, { recursive: true });
    await copyDir(baseLibDir,outLibDir)
    if(isPlugins){
      await copyDir(userLibDir,outLibDir)
      copySdk(path.resolve(proPath,'dcloud_uniplugins.json') ,dcloud_uniplugins)
      addLog("第三方sdk复制完成:" + data.projectName, data.projectName);
    
    }
    addLog("初始化libs完成:" + data.projectName, data.projectName);
    // 获取项目配置文件
    let manifestFile = JSON5.parse(
      fs.readFileSync(
        path.resolve(proPath,
          "src/manifest.json"
        ),
        "utf-8"
      )
    );
    // 移动文件到对应目录  签名
    let buildList =
      data.type == "Android"
        ? [
            androidChangeFile(data, manifestFile),
            androidSign(data, projectData),
          ]
        : [iosChangeFile(data, manifestFile), iosSign(data, projectData)];
    buildList.forEach((item) => {
      item
        .then(() => {
          endItem.push(1);
        })
        .catch(() => {
          endItem.push(0);
        })
        .finally(() => {
          buildAll(data, manifestFile, projectData)
            .then((bool) => {
              bool && resolve();
            })
            .catch(reject);
        });
    });
  });
}

// 全部准备结束
function buildAll({ projectName, type }, manifestFile, projectData) {
  let endPromise = type == "Android" ? outAndroid : outIos;
  return new Promise((resolve, reject) => {
    if (endItem.length < 2) return resolve(false);
    if (endItem.includes(0)) {
      addLog("准备阶段失败", projectName);
      console.log("准备阶段失败", projectName);
      endItem = [];
      reject();
    } else {
      addLog("准备阶段完成执行打包,生成对应文件", projectName);
      endItem = [];
      endPromise(projectName, manifestFile, projectData)
        .then(() => {
          addLog("打包结束", projectName);
          resolve(true);
        })
        .catch(() => {
          addLog("打包失败", projectName);
          reject();
        });
    }
  });
}

// 进入队列
function buildApp(data) {
  addLog("加入打包，前面还有" + queue.length + "个项目", data.projectName);
  proPath = data.projectPath || path.join(__dirname, "../project",  data.projectName);
  getDir()
  queue.push(data);
  runQueue();
}

// 获取打包队列状态
function getBuildStatus(projectName) {
  let index = queue.findIndex((item) => item.projectName == projectName);
  if (index == -1) {
    let data = global.building.find((item) => item.projectName == projectName);
    if (data) {
      return { data: "正在打包项目", status: 0, projectName };
    } else {
      return {
        data: { text: "没有在打包队列中，打包完成" },
        status: 1,
        projectName,
      };
    }
  } else {
    return {
      data: "正在打包,前面还有" + index + "个项目",
      status: 0,
      projectName,
    };
  }
}
// 目前使用npm run build:app-android会在/dist/build/app-plus下生成app打包资源。
// 如需制作wgt包，将app-plus中的文件压缩成zip（注意：不要包含app-plus目录），
// 再重命名为${appid}.wgt， appid为manifest.json文件中的appid。
async function buildWgt(data){
  // 把/dist/build下面的app-plus 压缩成zip 然后重命名成appid.wgt
  console.log("开始构建项目", data);
  proPath = data.projectPath || path.join(__dirname, "../project", projectName);
  let profilePath =  path.resolve(proPath,'dist/build/app/')
  let wgtName = data.alias.toUpperCase()
  let outPath = path.resolve(__dirname, "../../public/uploadfile/",data.projectName,wgtName +'.wgt')
  compressing.zip.compressDir(profilePath, outPath,{ignoreBase:true}).then(res => {
    global.building = global.building.filter(item=>item.projectName != data.projectName);
    addLog("构建成功:返回wgt下载地址", data.projectName);
    let projectData = getData(data.projectName);
    projectData["outWgt"] = "/uploadfile/"+data.projectName+"/"+wgtName+".wgt"
    setData(data.projectName, projectData);
  }).catch(err => {
    global.building = global.building.filter(item=>item.projectName != data.projectName);
    addLog("打包失败", data);
  })
}
module.exports = {
  buildApp,
  buildWgt,
  getBuildStatus,
};
